home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 July: Mac OS SDK / Dev.CD Jul 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK / Mac OS USB DDK 1.4.1 / Examples / USBModem / ModemDriver.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-25  |  40.2 KB  |  1,593 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        ModemDriver.c
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998-1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     File Ownership:
  11.  
  12.         DRI:                xxx put dri here xxx
  13.  
  14.         Other Contact:        xxx put other contact here xxx
  15.  
  16.         Technology:            xxx put technology here xxx
  17.  
  18. */
  19.  
  20. #include <DriverServices.h>
  21.  
  22. #include "Modem.h"
  23. #include "ModemDriver.h"
  24. #include "ShimSerialHAL.h"
  25.  
  26. enum
  27. {
  28.     kUSBv12    =    0x01200000
  29. };
  30.  
  31. static serPB         gSerialGlobals;
  32. static USBPB        syncPB, interruptPB, readPB, writePB, stallPB, delayPB;
  33. static UInt16        deadman = 20;
  34. static OSStatus        configerr = noErr;
  35. volatile Boolean    configured = false;
  36. UInt32                usbVersion = 0;
  37. Boolean                gUSBVersionNeedsBulkFixPresent;
  38.  
  39. /************************************************************************************/
  40. //
  41. //    CheckUSBVersion
  42. //
  43. //    Determines whether it's USB1.2 (less requires doing safe bulk calls)
  44. //
  45. /************************************************************************************/
  46. void    CheckUSBVersion(void)
  47. {
  48. OSStatus    err = 0;
  49.  
  50.     TraceMessage(0, "\pEntering CheckUSBVersion;g");
  51.     
  52.     err = Gestalt('usbv', (long*)&usbVersion);
  53.         
  54.     if (err == noErr)
  55.         gUSBVersionNeedsBulkFixPresent = (usbVersion < kUSBv12);
  56. }
  57.  
  58. /************************************************************************************/
  59. //
  60. //    SecondaryUSBBulkRead
  61. //
  62. //    USBBulkRead called at safe secondary int. time (USB 1.1 or earlier)
  63. //
  64. /************************************************************************************/
  65. OSStatus SecondaryUSBBulkRead(void *pb, void *result)
  66. {
  67.     *(OSStatus*)result = USBBulkRead((USBPB*)pb);
  68.     return noErr;
  69. }
  70.  
  71. /************************************************************************************/
  72. //
  73. //    SecondaryUSBBulkWrite
  74. //
  75. //    USBBulkWrite called at safe secondary int. time (USB 1.1 or earlier)
  76. //
  77. /************************************************************************************/
  78. OSStatus SecondaryUSBBulkWrite(void *pb, void *result)
  79. {
  80.     *(OSStatus*)result = USBBulkWrite((USBPB*)pb);
  81.     return noErr;
  82. }
  83.  
  84. /************************************************************************************/
  85. //
  86. //    SafeUSBBulkRead
  87. //
  88. //    Determines which version of the bulk read to call.
  89. //
  90. /************************************************************************************/
  91. OSStatus SafeUSBBulkRead(USBPB *pb)
  92. {
  93.     OSStatus    result;
  94.  
  95.     if (gUSBVersionNeedsBulkFixPresent)
  96.     {
  97.         // Use CallSecondaryInterruptHandler2 to call USBBulkRead if
  98.         // less than USB v1.2 present
  99.         CallSecondaryInterruptHandler2(SecondaryUSBBulkRead, nil, pb, &result);
  100.     }
  101.     else
  102.         result = USBBulkRead(pb);
  103.         
  104.     return result;
  105. }
  106.  
  107. /************************************************************************************/
  108. //
  109. //    SafeUSBBulkWrite
  110. //
  111. //    Determines which version of the bulk write to call.
  112. //
  113. /************************************************************************************/
  114. OSStatus SafeUSBBulkWrite(USBPB *pb)
  115. {
  116.     OSStatus    result;
  117.  
  118.     if (gUSBVersionNeedsBulkFixPresent)
  119.     {
  120.         // Use CallSecondaryInterruptHandler2 to call USBBulkWrite if
  121.         // less than USB v1.2 present
  122.         CallSecondaryInterruptHandler2(SecondaryUSBBulkWrite, nil, pb, &result);
  123.     }
  124.     else
  125.         result = USBBulkWrite(pb);
  126.         
  127.     return result;
  128. }
  129.  
  130. /************************************************************************************/
  131. //
  132. //    USBStatus
  133. //
  134. //    Determines which status call to make.
  135. //
  136. /************************************************************************************/
  137.  
  138. void USBStatus(UInt32 level, USBDeviceRef ref, void *pointer, UInt32 value)
  139. {
  140.     
  141.     if (usbVersion < kUSBv12)
  142.     {
  143.         USBExpertStatus(ref, pointer, value);
  144.     } else {
  145.         USBExpertStatusLevel(level, ref, pointer, value);
  146.     }
  147. }
  148.  
  149. /************************************************************************************/
  150. //
  151. //    immediateError
  152. //
  153. //    Determines whether it's an error or just pending.
  154. //
  155. /************************************************************************************/
  156.  
  157. static Boolean immediateError(OSStatus err)
  158. {
  159.     return ((err != kUSBPending) && (err != noErr));
  160. }
  161.  
  162. /************************************************************************************/
  163. //
  164. //    ConfigurationHandler
  165. //
  166. //    Configures the USB Serial Device (Modem).
  167. //
  168. /************************************************************************************/
  169.  
  170. static void ConfigurationHandler(USBPB *pb)
  171. {
  172. serPB         *sp = &gSerialGlobals;
  173.  
  174. //    TraceMessage(0, kCRMName"- Entering ConfigurationHandler");
  175.     StatusMessage(sp->deviceRef, kCRMName"- Entering ConfigurationHandler", pb->usbRefcon);
  176.     
  177.     if(pb->usbStatus != noErr)
  178.     {
  179.         if((sp->onError == kReset) && (sp->retries > 0))
  180.         {
  181.             /* no idea what to do now?? */
  182.             USBExpertFatalError(sp->deviceRef, pb->usbStatus, sp->errorString, pb->usbRefcon);
  183.             
  184.             /* Mark port as errored */
  185.             configured = true;
  186.             configerr = pb->usbStatus;
  187.         }
  188.         else
  189.         {
  190.             StatusMessage(sp->deviceRef, sp->errorString, pb->usbStatus);
  191.             pb->usbRefcon = sp->onError;
  192.  
  193.             USBClearPipeStallByReference(pb->usbReference);
  194.             
  195.             /* we'll delay coming back to here */
  196.             sp->retries--;
  197.  
  198.             pb->usbReqCount = 0;
  199.             USBDelay(pb);
  200.         }        
  201.         return;
  202.     }
  203.  
  204.     sp->onError = kReset;
  205.     
  206.     do{switch(pb->usbRefcon++)
  207.     {
  208.         case kCommConfig:
  209.         
  210.             /* Need to find an interface with a communication class in it */
  211.             pb->usbClassType = kUSBCommClass;
  212.             pb->usbSubclass = 2;                        /* Abstract Control Model */
  213.             pb->usbProtocol = 1;                        /* v.25ter (Hayes AT Command set) */
  214.             pb->usb.cntl.WValue = 0;
  215.             pb->usb.cntl.WIndex = 0;
  216.             pb->usbReqCount = 0;
  217.             pb->usbBuffer = nil;
  218.             pb->usbFlags = 0;
  219.             
  220.             if (sp->retries > 0)
  221.             {
  222.                 sp->onError = kCommConfig;
  223.             } else {
  224.                 sp->onError = kReset;
  225.             }            
  226.             noteError(kCRMName"- Finding the Comm Class Interface");            
  227.             if(immediateError(configerr = USBFindNextInterface(pb)))
  228.             {
  229.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  230.                 configured = true;
  231.             }
  232.             
  233.         break;
  234.  
  235.         case kSetConfig:
  236.             StatusMessage(sp->deviceRef, kCRMName"- Configuration Number - ", pb->usb.cntl.WValue);
  237.             StatusMessage(sp->deviceRef, kCRMName"- Interface Number - ", pb->usb.cntl.WIndex);
  238.             
  239.             /* Remember the interface number */
  240.             sp->interfacenum = pb->usb.cntl.WIndex;
  241.             
  242.             /* Open the device based on the config found */            
  243.             if (sp->retries > 0)
  244.             {
  245.                 sp->onError = kSetConfig;
  246.             } else {
  247.                 sp->onError = kReset;
  248.             }
  249.             noteError(kCRMName"- Setting the configuration");
  250.             if(immediateError(configerr = USBSetConfiguration(pb)))
  251.             {
  252.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  253.                 configured = true;
  254.             }
  255.         
  256.         break;
  257.         
  258.         case kGetCommInterface:
  259.             StatusMessage(sp->deviceRef, kCRMName"- Number of interfaces in Configuration - ", pb->usbOther);
  260.             
  261.             /* Get the interface reference number */
  262.             if (sp->retries > 0)
  263.             {
  264.                 sp->onError = kGetCommInterface;
  265.             } else {
  266.                 sp->onError = kReset;
  267.             }
  268.             pb->usbOther = 0;
  269.             
  270.             noteError(kCRMName"- Getting Comm Class interface");            
  271.             if(immediateError(configerr = USBNewInterfaceRef(pb)))
  272.             {
  273.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  274.                 configured = true;
  275.             }
  276.         
  277.         break;
  278.     
  279.         case kSetCommInterface:
  280.             StatusMessage(sp->deviceRef, kCRMName"- Comm. Interface Ref - ", pb->usbReference);
  281.             
  282.             /* Set the interface (Comm) */
  283.             pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBNone, kUSBStandard, kUSBInterface);                        
  284.             pb->usb.cntl.BRequest = kUSBRqSetInterface;
  285.             pb->usb.cntl.WValue = 0;
  286.             pb->usb.cntl.WIndex = sp->interfacenum;
  287.             pb->usbReqCount = 0;
  288.             pb->usbBuffer = nil;
  289.             if (sp->retries > 0)
  290.             {
  291.                 sp->onError = kSetCommInterface;
  292.             } else {
  293.                 sp->onError = kReset;
  294.             }
  295.  
  296.             noteError(kCRMName"- Setting Comm Class interface");
  297.             if(immediateError(configerr = USBDeviceRequest(pb)))
  298.             {
  299.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  300.             }
  301.             break;
  302.  
  303.         case kConfigureCommInterface:
  304.             
  305.             /* configure the Comm Class interface */
  306.             if (sp->retries > 0)
  307.             {
  308.                 sp->onError = kConfigureCommInterface;
  309.             } else {
  310.                 sp->onError = kReset;
  311.             }
  312.             
  313.             noteError(kCRMName"- Configuring the Comm Class interface");
  314.             if(immediateError(configerr = USBConfigureInterface(pb)))
  315.             {    
  316.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  317.                 configured = true;
  318.             }
  319.             
  320.         break;
  321.         
  322.         case kGetInterruptEndpoint:
  323.             StatusMessage(sp->deviceRef, kCRMName"- Number of pipes in Interface - ", pb->usbOther);
  324.             
  325.             /* Get the Comm Class interrupt endpoint */
  326.             pb->usbFlags = kUSBIn;
  327.             pb->usbClassType = kUSBInterrupt;
  328.             if (sp->retries > 0)
  329.             {
  330.                 sp->onError = kGetInterruptEndpoint;
  331.             } else {
  332.                 sp->onError = kReset;
  333.             }
  334.             
  335.             noteError(kCRMName"- Finding the interrupt endpoint");
  336.             if(immediateError(configerr = USBFindNextPipe(pb)))
  337.             {    
  338.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  339.                 configured = true;
  340.             }
  341.             
  342.         break;
  343.         
  344.         case kDataConfig:
  345.             StatusMessage(sp->deviceRef, kCRMName"- Interrupt In Ref - ", pb->usbReference);
  346.             
  347.             /* Interrupt Endpoint is open - remember the ref */
  348.             sp->interrupt = pb->usbReference;
  349.             
  350.             /* Need to find an interface with a data class in it */
  351.             pb->usbClassType = kUSBDataClass;
  352.             pb->usbSubclass = 0;
  353.             pb->usbProtocol = 0;
  354.             pb->usb.cntl.WValue = 0;
  355.             pb->usb.cntl.WIndex = 0;
  356.             pb->usbReqCount = 0;
  357.             pb->usbBuffer = nil;
  358.             pb->usbFlags = 0;
  359.             pb->usbOther = 0;
  360.             pb->usbReference = sp->deviceRef;        // Set it back to the device
  361.             if (sp->retries > 0)
  362.             {
  363.                 sp->onError = kDataConfig;
  364.             } else {
  365.                 sp->onError = kReset;
  366.             }
  367.  
  368.             noteError(kCRMName"- Finding the Data Interface");
  369.             if(immediateError(configerr = USBFindNextInterface(pb)))
  370.             {
  371.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  372.                 configured = true;
  373.             }
  374.             
  375.         break;
  376.         
  377.         case kGetDataInterface:
  378.             StatusMessage(sp->deviceRef, kCRMName"- Configuration Number - ", pb->usb.cntl.WValue);
  379.             StatusMessage(sp->deviceRef, kCRMName"- Interface Number - ", pb->usb.cntl.WIndex);
  380.             
  381.             /* Remember the interface number */
  382.             sp->interfacenum = pb->usb.cntl.WIndex;
  383.             
  384.             /* Get the interface reference number */
  385.             if (sp->retries > 0)
  386.             {
  387.                 sp->onError = kGetDataInterface;
  388.             } else {
  389.                 sp->onError = kReset;
  390.             }            
  391.             pb->usbOther = 0;
  392.             
  393.             noteError(kCRMName"- Getting Data Class interface");
  394.             if(immediateError(configerr = USBNewInterfaceRef(pb)))
  395.             {
  396.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  397.                 configured = true;
  398.             }
  399.         
  400.         break;
  401.  
  402.         case kConfigureDataInterface:
  403.             StatusMessage(sp->deviceRef, kCRMName"- Data Interface Ref - ", pb->usbReference);
  404.             
  405.             /* configure the Data Class interface */
  406.             if (sp->retries > 0)
  407.             {
  408.                 sp->onError = kConfigureDataInterface;
  409.             } else {
  410.                 sp->onError = kReset;
  411.             }
  412.             
  413.             noteError(kCRMName"- Configuring the Data Class interface");
  414.             if(immediateError(configerr = USBConfigureInterface(pb)))
  415.             {    
  416.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  417.                 configured = true;
  418.             }
  419.             
  420.         break;
  421.             
  422.         case kGetBulkOutEndpoint:
  423.             StatusMessage(sp->deviceRef, kCRMName"- Number of pipes in Interface - ", pb->usbOther);
  424.             
  425.             /* Find the out endpoint */
  426.             pb->usbFlags = kUSBOut;
  427.             pb->usbClassType = kUSBBulk;
  428.             pb->usbSubclass = 0;            /* Find the first one */
  429.             if (sp->retries > 0)
  430.             {
  431.                 sp->onError = kGetBulkOutEndpoint;
  432.             } else {
  433.                 sp->onError = kReset;
  434.             }
  435.             
  436.             noteError(kCRMName"- Finding the bulk out endpoint");
  437.             if(immediateError(configerr = USBFindNextPipe(pb)))
  438.             {    
  439.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  440.                 configured = true;
  441.             }
  442.             
  443.         break;
  444.     
  445.         case kGetBulkInEndpoint:
  446.             StatusMessage(sp->deviceRef, kCRMName"- Bulk Out Endpoint - ", pb->usbReference);
  447.             
  448.             /* Out Endpoint is open - remember the ref */
  449.             sp->bulkOut = pb->usbReference;
  450.             
  451.             /* Find the in endpoint */
  452.             pb->usbFlags = kUSBIn;
  453.             pb->usbClassType = kUSBBulk;
  454.             pb->usbSubclass = 0;            /* Find the first one */
  455.             if (sp->retries > 0)
  456.             {
  457.                 sp->onError = kGetBulkInEndpoint;
  458.             } else {
  459.                 sp->onError = kReset;
  460.             }
  461.             
  462.             noteError(kCRMName"- Finding the bulk in endpoint");
  463.             if(immediateError(configerr = USBFindNextPipe(pb)))
  464.             {    
  465.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  466.                 configured = true;
  467.             }
  468.             
  469.         break;
  470.     
  471.         case kConfigDone:
  472.             StatusMessage(sp->deviceRef, kCRMName"- Bulk In Endpoint - ", pb->usbReference);
  473.             
  474.             /* In Endpoint is open - remember the ref */
  475.             sp->bulkIn = pb->usbReference;
  476.             
  477.             StartStatusMonitor(sp->interrupt);
  478.             
  479.             // device is fully configured, ready for somebody to set the baud rate, etc.
  480.             // and start reading/writing to the bulk endpoints
  481.             syncPB.usbStatus = kAvailableStatus;
  482.             StatusMessage(sp->deviceRef, kCRMName"- Configuration complete.", 0);
  483.             configured = true;
  484.         break;
  485.     
  486.         default:
  487.             noteError(kCRMName"- Internal Error unused case in Configuration handler");            
  488.             StatusMessage(sp->deviceRef, sp->errorString, (pb->usbRefcon-1));
  489.             configured = true;
  490.             configerr = -1;
  491.         break;
  492.     }
  493.     break;    /* only execute once, unless continue used */
  494.     }while(1);    /* so case can be reentered with a continue */
  495. }
  496.  
  497. UInt16    statusData[8];
  498.  
  499. /************************************************************************************/
  500. //
  501. //    ResetInterruptPB
  502. //
  503. //    Re-initialize the interrupt PB.
  504. //
  505. /************************************************************************************/
  506.  
  507. static void ResetInterruptPB(USBPB *pb)
  508. {
  509.     pb->usbReqCount = 16;
  510.     pb->usbBuffer = &statusData;
  511.     pb->usbStatus = noErr;
  512. }
  513.  
  514. UInt8     Intrretries = 0;
  515.  
  516. /************************************************************************************/
  517. //
  518. //    interruptCompletion
  519. //
  520. //    Interrupt completion handler.
  521. //
  522. /************************************************************************************/
  523.  
  524. static void interruptCompletion(USBPB *pb)
  525. {
  526.     serPB         *sp = &gSerialGlobals;
  527.     OSStatus    err;
  528.     unsigned char        newErrs = 0;
  529.     ShimSerialGlobals    *globals = gGlobals;
  530.     
  531.     TraceMessage(0, kCRMName"- Entering interruptCompletion");
  532.     
  533.     if (pb->usbStatus != kUSBAbortedError)    // are we being asked to quit?
  534.     {
  535.         if (pb->usbStatus != noErr)
  536.         {
  537.             StatusMessage(sp->deviceRef, kCRMName"- ModemDriver: interruptCompletion error ", pb->usbStatus);
  538.             if (pb->usbStatus == kUSBEndpointStallErr)
  539.             {
  540.                 ClearDevice();
  541.             }
  542.             USBClearPipeStallByReference(gSerialGlobals.interrupt);
  543.             
  544.             Intrretries++;
  545.             if (Intrretries > 10)
  546.                 return;                    // we'll just give up for now
  547.                 
  548.             DoDelay();
  549.  
  550.         } else {
  551.             Intrretries = 0;
  552.             TraceMessage(0, kCRMName"- Interrupt received");
  553.             if ((pb->usbActCount > 2) && ((statusData[0] & 0x00FF) == kSerialState))
  554.             {
  555.                 sp->modemUSBStatus = HostToUSBWord(statusData[4]);
  556.                 
  557.                 if (sp->modemUSBStatus & kUSBParityErr) 
  558.                     newErrs |= parityErr;
  559.                 if (sp->modemUSBStatus & kUSBFramingErr) 
  560.                     newErrs |= framingErr;
  561.                 if (sp->modemUSBStatus & kUSBHwOverRunErr) 
  562.                     newErrs |= hwOverrunErr;
  563.                     
  564.                 globals->serStat.cumErrs |= newErrs;
  565.                 StatusMessage(sp->deviceRef, kCRMName"- Modem Serial state - ", sp->modemUSBStatus);
  566.             }
  567.         }
  568.         
  569.         ResetInterruptPB(pb);
  570.  
  571.         if(immediateError(err = USBIntRead(pb)))
  572.         {
  573.             StatusMessage(sp->deviceRef, kCRMName"- Couldn't queue interrupt read!", err);
  574.         }
  575.     }
  576. }
  577.  
  578. /************************************************************************************/
  579. //
  580. //    StartStatusMonitor
  581. //
  582. //    Kick off the interrupt mechanism.
  583. //
  584. /************************************************************************************/
  585.  
  586. static void StartStatusMonitor(USBPipeRef interruptPipe)
  587. {
  588.     USBPB        *pb = &interruptPB;
  589.     serPB         *sp = &gSerialGlobals;
  590.     OSStatus    err;
  591.     
  592.     TraceMessage(0, kCRMName"- Entering StartStatusMonitor");
  593.     
  594.     InitializePB(pb, interruptPipe, interruptCompletion);
  595.  
  596.     ResetInterruptPB(pb);
  597.  
  598.     if(immediateError(err = USBIntRead(pb)))
  599.     {
  600.         StatusMessage(sp->deviceRef, kCRMName"- Couldn't start interrupt read!", err);
  601.     }        
  602.  
  603. }
  604.  
  605. /************************************************************************************/
  606. //
  607. //    syncCompletion
  608. //
  609. //    Completion handler for all sync (setup) requests.
  610. //
  611. /************************************************************************************/
  612.  
  613. static void syncCompletion(USBPB *pb)
  614. {
  615.     serPB     *sp = &gSerialGlobals;
  616.  
  617.     TraceMessage(0, kCRMName"- Entering syncCompletion");
  618.  
  619.     if (pb->usbStatus != noErr)
  620.     {
  621.         USBExpertFatalError(sp->deviceRef, pb->usbStatus, kCRMName"- ModemDriver: syncCompletion err for bRequest", pb->usb.cntl.BRequest);
  622.         if (pb->usbStatus == kUSBEndpointStallErr)
  623.         {
  624. //            ClearDevice();
  625.         }
  626.         USBClearPipeStallByReference(pb->usbReference);
  627.     }
  628.         
  629.     pb->usbStatus = kAvailableStatus;
  630. }
  631.  
  632. /************************************************************************************/
  633. //
  634. //    TimeoutPrevRequest
  635. //
  636. //    Timeout for all sync. requests.
  637. //
  638. /************************************************************************************/
  639.  
  640. Boolean TimeoutPrevRequest(void)
  641. {
  642.     USBPB        *pb = &syncPB;
  643.     serPB         *sp = &gSerialGlobals;
  644.     AbsoluteTime    startTime;
  645.     Duration        elapsedTime;
  646.  
  647.     if (pb->usbStatus == kAvailableStatus)
  648.         return false;
  649.     
  650.     startTime = UpTime();
  651.  
  652.     while (pb->usbStatus != kAvailableStatus){
  653.         elapsedTime = AbsoluteDeltaToDuration(UpTime(), startTime);
  654.         if (elapsedTime < 0) elapsedTime = elapsedTime/(-1000);      // make sure it's in milliseconds
  655.         if (elapsedTime > 100*durationMillisecond){
  656.             StatusMessage(sp->deviceRef, kCRMName"- Modem driver, device request timeout - aborting", 0);
  657.             USBAbortPipeByReference(pb->usbReference);
  658.             return true;
  659.         }
  660.     }
  661.     return false;
  662. }
  663.  
  664. /************************************************************************************/
  665. //
  666. //    TimeoutStallRequest
  667. //
  668. //    Timeout for all stall clear requests.
  669. //
  670. /************************************************************************************/
  671.  
  672. Boolean TimeoutStallRequest(void)
  673. {
  674.     USBPB            *pb = &stallPB;
  675.     serPB             *sp = &gSerialGlobals;
  676.     AbsoluteTime    startTime;
  677.     Duration        elapsedTime;
  678.  
  679.     if (pb->usbStatus == kAvailableStatus)
  680.         return false;
  681.     
  682.     startTime = UpTime();
  683.  
  684.     while (pb->usbStatus != kAvailableStatus){
  685.         elapsedTime = AbsoluteDeltaToDuration(UpTime(), startTime);
  686.         if (elapsedTime < 0) elapsedTime = elapsedTime/(-1000);      // make sure it's in milliseconds
  687.         if (elapsedTime > 100*durationMillisecond){
  688.             StatusMessage(sp->deviceRef, kCRMName"- Modem driver, Stall timeout - aborting", 0);
  689.             USBAbortPipeByReference(pb->usbReference);
  690.             return true;
  691.         }
  692.     }
  693.     return false;
  694. }
  695.  
  696. /************************************************************************************/
  697. //
  698. //    TimeoutDelayRequest
  699. //
  700. //    Timeout for delay requests.
  701. //
  702. /************************************************************************************/
  703.  
  704. Boolean TimeoutDelayRequest(void)
  705. {
  706.     USBPB            *pb = &delayPB;
  707.     serPB             *sp = &gSerialGlobals;
  708.     AbsoluteTime    startTime;
  709.     Duration        elapsedTime;
  710.  
  711.     if (pb->usbStatus == kAvailableStatus)
  712.         return false;
  713.     
  714.     startTime = UpTime();
  715.  
  716.     while (pb->usbStatus != kAvailableStatus){
  717.         elapsedTime = AbsoluteDeltaToDuration(UpTime(), startTime);
  718.         if (elapsedTime < 0) elapsedTime = elapsedTime/(-1000);      // make sure it's in milliseconds
  719.         if (elapsedTime > 100*durationMillisecond){
  720.             return true;
  721.         }
  722.     }
  723.     return false;
  724. }
  725.  
  726. /************************************************************************************/
  727. //
  728. //    USBSetBaudRate
  729. //
  730. //    Set up and send SetLineCoding request for baud rate only.
  731. //
  732. /************************************************************************************/
  733.  
  734. void USBSetBaudRate(UInt32 baudRate)
  735. {
  736.     USBPB        *pb = &syncPB;
  737.     serPB         *sp = &gSerialGlobals;
  738.     OSStatus     err;
  739.     UInt16        temp = 0;
  740.     UInt16        rateh;
  741.     Boolean        setdte = false;
  742.     
  743.     TraceMessage(0, kCRMName"- Entering USBSetBaudRate");
  744.     
  745.     if (TimeoutPrevRequest())
  746.         return;
  747.     
  748.     if (baudRate == kMaxBaudRate)        // We're going to lock to max for the moment
  749.     {
  750.     
  751.         // convert baudrate            I hate Intel...
  752.         temp = baudRate % 0x10000;
  753.         rateh = USBToHostWord(temp);
  754.         if (rateh != sp->Line_Settings.DTERate1)
  755.         {
  756.             sp->Line_Settings.DTERate1 = rateh;
  757.             setdte = true;
  758.         }
  759.         temp = baudRate / 0x10000;
  760.         rateh = USBToHostWord(temp);
  761.         if (rateh != sp->Line_Settings.DTERate2)
  762.         {
  763.             sp->Line_Settings.DTERate2 = rateh;
  764.             setdte = true;
  765.         }
  766.     
  767.         // Only do it if it's changing
  768.         if (setdte)
  769.         {        
  770.             pb->usbStatus = noErr;
  771.             pb->pbVersion = kUSBCurrentPBVersion;
  772.             pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);    
  773.             pb->usb.cntl.BRequest = kSetLineCoding;
  774.             pb->usb.cntl.WValue = 0;
  775.             pb->usb.cntl.WIndex = 1; 
  776.             pb->usbReqCount = sizeof(sp->Line_Settings)-1;
  777.             pb->usbBuffer = &sp->Line_Settings;
  778.  
  779.             if(immediateError(err = USBDeviceRequest(pb)))
  780.             {
  781.                 StatusMessage(sp->deviceRef, kCRMName"- Modem driver Setting baud rate", err);
  782.                 pb->usbStatus = kAvailableStatus;
  783.             }
  784.         }
  785.     }
  786. }
  787.  
  788. /************************************************************************************/
  789. //
  790. //    USBSetLineCoding
  791. //
  792. //    Set up and send SetLineCoding Request for all settings.
  793. //
  794. /************************************************************************************/
  795.  
  796. void USBSetLineCoding(LineParms Line_Coding)
  797. {
  798.     USBPB        *pb = &syncPB;
  799.     serPB         *sp = &gSerialGlobals;
  800.     OSStatus     err;
  801.     Boolean        setcoding = false;
  802.     
  803.     TraceMessage(0, kCRMName"- Entering USBSetLineCoding");
  804.     
  805.     if (TimeoutPrevRequest())
  806.         return;
  807.         
  808.     // save the settings only if they've changed
  809.     if (Line_Coding.CharFormat != sp->Line_Settings.CharFormat)
  810.     {
  811.         sp->Line_Settings.CharFormat = Line_Coding.CharFormat;
  812.         setcoding = true;
  813.     }
  814.     if (Line_Coding.ParityType != sp->Line_Settings.ParityType)
  815.     {
  816.         sp->Line_Settings.ParityType = Line_Coding.ParityType;
  817.         setcoding = true;
  818.     }
  819.     if (Line_Coding.DataBits != sp->Line_Settings.DataBits)
  820.     {
  821.         sp->Line_Settings.DataBits = Line_Coding.DataBits;
  822.         setcoding = true;
  823.     }
  824.     
  825.     // Don't do this if they haven't changed
  826.     if (setcoding)
  827.     {
  828.         pb->usbStatus = noErr;
  829.         pb->pbVersion = kUSBCurrentPBVersion;
  830.         pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);                
  831.         pb->usb.cntl.BRequest = kSetLineCoding;
  832.         pb->usb.cntl.WValue = 0;
  833.         pb->usb.cntl.WIndex = 1; 
  834.         pb->usbReqCount = sizeof(sp->Line_Settings)-1;
  835.         pb->usbBuffer = &sp->Line_Settings;
  836.  
  837.         if(immediateError(err = USBDeviceRequest(pb)))
  838.         {
  839.             StatusMessage(sp->deviceRef, kCRMName"- Modem driver Setting Line Coding", err);
  840.             pb->usbStatus = kAvailableStatus;
  841.         }
  842.     }
  843. }
  844.  
  845. /************************************************************************************/
  846. //
  847. //    USBSetControlLineState
  848. //
  849. //    Set up and send SetControlLineState (DTR and RTS).
  850. //
  851. /************************************************************************************/
  852.  
  853. void USBSetControlLineState(void)
  854. {
  855.     USBPB        *pb = &syncPB;
  856.     serPB         *sp = &gSerialGlobals;
  857.     OSStatus     err;
  858.     
  859.     TraceMessage(0, kCRMName"- Entering USBSetControlLineState");
  860.     
  861.     if (TimeoutPrevRequest())
  862.         return;
  863.  
  864.     pb->usbStatus = noErr;
  865.     pb->pbVersion = kUSBCurrentPBVersion;
  866.     pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);
  867.     pb->usb.cntl.BRequest = kSetControlLineState;
  868.     pb->usb.cntl.WValue = sp->lineState;
  869.     pb->usb.cntl.WIndex = 1; 
  870.     pb->usbReqCount = 0;
  871.     pb->usbBuffer = 0;
  872.  
  873.     if(immediateError(err = USBDeviceRequest(pb)))
  874.     {
  875.         StatusMessage(sp->deviceRef, kCRMName"- Modem driver Setting Control Line State", err);
  876.         pb->usbStatus = kAvailableStatus;
  877.     }
  878. }
  879.  
  880. /************************************************************************************/
  881. //
  882. //    USBSetDTRState
  883. //
  884. //    Set the DTR state.
  885. //
  886. /************************************************************************************/
  887.  
  888. void USBSetDTRState(Boolean state)
  889. {
  890.     serPB     *sp = &gSerialGlobals;
  891.  
  892.     TraceMessage(0, kCRMName"- Entering USBSetDTRState");
  893.  
  894.     if (state)
  895.     {
  896.         sp->lineState |= kDTROn;
  897.     } else {
  898.         if (!sp->DTRClose)
  899.             sp->lineState &= (kDTROff + kRTSOn);
  900.     }
  901. }
  902.  
  903. /************************************************************************************/
  904. //
  905. //    USBSetRTSState
  906. //
  907. //    Set the RTS state.
  908. //
  909. /************************************************************************************/
  910.  
  911. void USBSetRTSState(Boolean state)
  912. {
  913.     serPB     *sp = &gSerialGlobals;
  914.  
  915.     TraceMessage(0, kCRMName"- Entering USBSetRTSState");
  916.  
  917.     if (state)
  918.     {
  919.         sp->lineState |= kRTSOn;
  920.     } else {
  921.         sp->lineState &= (kRTSOff + kDTROn);
  922.     }
  923. }
  924.  
  925. /************************************************************************************/
  926. //
  927. //    USBSendBreak
  928. //
  929. //    Set up and send break request.
  930. //
  931. /************************************************************************************/
  932.  
  933. void USBSendBreak(Boolean state)
  934. {
  935.     USBPB        *pb = &syncPB;
  936.     serPB         *sp = &gSerialGlobals;
  937.     OSStatus     err;
  938.     
  939.     TraceMessage(0, kCRMName"- Entering USBSendBreak");
  940.     
  941.     if (TimeoutPrevRequest())
  942.         return;
  943.  
  944.     pb->usbStatus = noErr;
  945.     pb->pbVersion = kUSBCurrentPBVersion;
  946.     pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);
  947.     pb->usb.cntl.BRequest = kSendBreak;
  948.     if (state)
  949.     {
  950.         pb->usb.cntl.WValue = kBreakOn;
  951.     } 
  952.     else 
  953.     {
  954.         pb->usb.cntl.WValue = kBreakOff;
  955.     }
  956.     pb->usb.cntl.WIndex = 1; 
  957.     pb->usbReqCount = 0;
  958.     pb->usbBuffer = 0;
  959.  
  960.     if(immediateError(err = USBDeviceRequest(pb)))
  961.     {
  962.         StatusMessage(sp->deviceRef, kCRMName"- Modem driver Setting Break State", err);
  963.         pb->usbStatus = kAvailableStatus;
  964.     }
  965. }
  966.  
  967. /************************************************************************************/
  968. //
  969. //    USBSetCloseDTR
  970. //
  971. //    Set the state of DTR on close.
  972. //
  973. /************************************************************************************/
  974.  
  975. void USBSetCloseDTR(void)
  976. {
  977.     serPB     *sp = &gSerialGlobals;
  978.  
  979.     TraceMessage(0, kCRMName"- Entering USBSetCloseDTR");
  980.  
  981.     sp->DTRClose = true;
  982. }
  983.  
  984. /************************************************************************************/
  985. //
  986. //    USBGetDCDValue
  987. //
  988. //    Gets the current state of CD.
  989. //
  990. /************************************************************************************/
  991.  
  992. UInt8 USBGetDCDValue(void)
  993. {
  994.     serPB     *sp = &gSerialGlobals;
  995.     UInt8    dcd = 0;
  996.  
  997.     TraceMessage(0, kCRMName"- Entering USBGetDCDValue");
  998.  
  999.     if (sp->modemUSBStatus & kUSBDCD) 
  1000.         dcd = 1;
  1001.         
  1002.     return dcd;
  1003. }
  1004.  
  1005. /************************************************************************************/
  1006. //
  1007. //    ModemDriverEntry
  1008. //
  1009. //    Initializes and starts the whole show.
  1010. //
  1011. /************************************************************************************/
  1012.  
  1013. OSStatus modemDriverEntry(USBDeviceRef device, USBDeviceDescriptor *desc)
  1014. {
  1015. static Boolean                 beenThereDoneThat = false;
  1016. static USBDeviceDescriptor     ourDeviceDescriptor;
  1017.  
  1018. //    DebugMessage(kCRMName"- Entering modemDriverEntry - Sync. point");
  1019.     TraceMessage(0, kCRMName"- Entering modemDriverEntry");
  1020.         
  1021.     if(beenThereDoneThat)
  1022.     {
  1023.         StatusMessage(device, kCRMName"- Modem driver called second time", 0);
  1024.         return -1;
  1025.     }
  1026.     beenThereDoneThat = true;
  1027.     
  1028.     ourDeviceDescriptor = *desc;
  1029.     gSerialGlobals.deviceDescriptor = &ourDeviceDescriptor;
  1030.     gSerialGlobals.deviceRef = device;
  1031.     
  1032.     InitializePB(&syncPB, device, syncCompletion);
  1033.     InitializePB(&stallPB, device, stallHandler);
  1034.     stallPB.usbStatus = kAvailableStatus;
  1035.     InitializePB(&delayPB, device, delayHandler);
  1036.     delayPB.usbStatus = kAvailableStatus;
  1037.  
  1038.     InitializePB(&gSerialGlobals.pb, device, ConfigurationHandler);
  1039.     gSerialGlobals.pb.usbRefcon = kCommConfig;    // Where we start from (kReset used for errors)
  1040.     gSerialGlobals.pb.usbBuffer = nil;
  1041.  
  1042.     gSerialGlobals.retries = 3;                // Let's keep it reasonable for now
  1043.     
  1044.     CheckUSBVersion();                        // Establish version and bulk fix flag before we start
  1045.     
  1046.     ConfigurationHandler(&gSerialGlobals.pb);
  1047.     
  1048.     if (configerr == 1)                        // pending's ok
  1049.     {
  1050.         return noErr;
  1051.     } else {
  1052.         return configerr;
  1053.     }
  1054. }
  1055.  
  1056. /************************************************************************************/
  1057. //
  1058. //    InitializePB
  1059. //
  1060. //    Initial a parameter block.
  1061. //
  1062. /************************************************************************************/
  1063.  
  1064. static void InitializePB(USBPB *pb, USBDeviceRef ref, USBCompletion handler)
  1065. {
  1066.     pb->pbVersion = kUSBCurrentPBVersion;
  1067.     pb->pbLength = sizeof(*pb);
  1068.     pb->usbReference = ref;
  1069.     pb->usbCompletion = handler;
  1070.     pb->usbStatus = noErr;
  1071.     
  1072. }
  1073.  
  1074. static errCount, readActive = false;
  1075.  
  1076. /************************************************************************************/
  1077. //
  1078. //    readCompletion
  1079. //
  1080. //    Completion handler for USB reads.
  1081. //
  1082. /************************************************************************************/
  1083.  
  1084. void readCompletion(USBPB *pb)
  1085. {
  1086.  
  1087.     TraceMessage(0,kCRMName"- Entering readCompletion");
  1088.     
  1089.     readActive = false;
  1090.     
  1091.     if (pb->usbStatus != kUSBAbortedError)    // are we being asked to quit?
  1092.     {
  1093.         if (pb->usbStatus == noErr)
  1094.         {
  1095.             LogData(kUSBIn, pb->usbActCount, pb->usbBuffer);
  1096.             HAL_ShimInput(pb->usbBuffer, pb->usbActCount);
  1097.         } else {
  1098.             StatusMessage(gSerialGlobals.deviceRef, kCRMName"- Read completion error ", pb->usbStatus);
  1099.                 
  1100.             if ((pb->usbStatus != kUSBUnderRunErr) && errCount++ < 10)
  1101.                 StatusMessage(gSerialGlobals.deviceRef, kCRMName"- Read completion error ", pb->usbStatus);
  1102.                 
  1103.             if (pb->usbStatus == kUSBEndpointStallErr)
  1104.             {
  1105. //                ClearDevice();
  1106.             }
  1107.             USBClearPipeStallByReference(gSerialGlobals.bulkIn);
  1108.             if (pb->usbActCount > 0)
  1109.             {
  1110.                 LogData(kUSBIn, pb->usbActCount, pb->usbBuffer);
  1111.                 HAL_ShimInput(pb->usbBuffer, pb->usbActCount);
  1112.             }
  1113.         }
  1114.     
  1115.         USBStartReadPolling();
  1116.     }
  1117. }
  1118.  
  1119. static UInt8    ioBuffer[64];
  1120.  
  1121. /************************************************************************************/
  1122. //
  1123. //    USBStartReadPolling
  1124. //
  1125. //    Start the USB read mechanism.
  1126. //
  1127. /************************************************************************************/
  1128.  
  1129. void USBStartReadPolling(void)
  1130. {
  1131.     OSStatus status;
  1132.     
  1133.     TraceMessage(0,kCRMName"- Entering USBStartReadPolling");
  1134.     
  1135.     if (gSerialGlobals.bulkIn && !readActive){
  1136.         InitializePB(&readPB, gSerialGlobals.bulkIn, readCompletion);
  1137.         readPB.usbBuffer = ioBuffer;
  1138.         readPB.usbReqCount = sizeof(ioBuffer);
  1139.         if(immediateError(status = SafeUSBBulkRead(&readPB)))
  1140. //        if(immediateError(status = USBBulkRead(&readPB)))
  1141.         {
  1142.             USBExpertFatalError(gSerialGlobals.deviceRef, status, kCRMName"- ModemDriver: Couldn't start read polling", 0);
  1143.             return;
  1144.         }
  1145.         readActive = true;
  1146.     }
  1147. }
  1148.  
  1149. /************************************************************************************/
  1150. //
  1151. //    USBStopReadPolling
  1152. //
  1153. //    You guessed it stop the USB read mechanism.
  1154. //
  1155. /************************************************************************************/
  1156.  
  1157. void USBStopReadPolling()
  1158. {
  1159.     StatusMessage(gSerialGlobals.deviceRef, kCRMName"- Aborting Bulk-in pipe", 0);
  1160.  
  1161.     if (gSerialGlobals.bulkIn){
  1162.         USBAbortPipeByReference(gSerialGlobals.bulkIn);
  1163.     }
  1164. }
  1165.  
  1166. static    UInt32    writeActive;
  1167.  
  1168. /************************************************************************************/
  1169. //
  1170. //    writeCompletion
  1171. //
  1172. //    USB write completion handler.
  1173. //
  1174. /************************************************************************************/
  1175.  
  1176. void writeCompletion(USBPB *pb)
  1177. {
  1178.     IOParam    *iopb;
  1179.     
  1180.     TraceMessage(0, kCRMName"- Entering writeCompletion");
  1181.     
  1182.     if (pb->usbStatus != kUSBAbortedError)    // are we being asked to quit?
  1183.     {
  1184.         if (pb->usbStatus != noErr) 
  1185.         {
  1186.             StatusMessage(gSerialGlobals.deviceRef, kCRMName"- Write Failed", pb->usbStatus);
  1187.             
  1188.             if (pb->usbStatus == kUSBEndpointStallErr)
  1189.             {
  1190. //                ClearDevice();
  1191.             }
  1192.             USBClearPipeStallByReference(pb->usbReference);
  1193.         }
  1194.     }
  1195.     writeActive--;
  1196.     gGlobals->pbOut = nil;
  1197.     iopb = (IOParam *)pb->usbRefcon;
  1198.     iopb->ioActCount = pb->usbActCount;
  1199.     
  1200.     ShimIOComplete((union ParamBlockRec *)iopb, pb->usbStatus ? ioErr : 0);
  1201.  
  1202. }
  1203.  
  1204. /************************************************************************************/
  1205. //
  1206. //    USBSerialWrite
  1207. //
  1208. //    USB serial write routine.
  1209. //
  1210. /************************************************************************************/
  1211.  
  1212. OSStatus USBSerialWrite(IOParam *pb)
  1213. {
  1214.     OSStatus     status = noErr;
  1215.     
  1216.     TraceMessage(0, kCRMName"- Entering USBSerialWrite");
  1217.     
  1218.     if (writeActive){
  1219.         StatusMessage(gSerialGlobals.deviceRef, kCRMName"- Overlapping writes!", writePB.usbStatus);
  1220.         status = ioErr;
  1221.     } else if (gSerialGlobals.bulkOut){
  1222.         
  1223.         InitializePB(&writePB, gSerialGlobals.bulkOut, writeCompletion);
  1224.         writePB.usbRefcon = (UInt32)pb;
  1225.         writePB.usbBuffer = pb->ioBuffer;
  1226.         writePB.usbReqCount = pb->ioReqCount;
  1227.         
  1228.         LogData(kUSBOut, writePB.usbReqCount, writePB.usbBuffer);
  1229.         
  1230.         if(immediateError(status = SafeUSBBulkWrite(&writePB)))
  1231. //        if(immediateError(status = USBBulkWrite(&writePB)))
  1232.         {
  1233.             StatusMessage(gSerialGlobals.deviceRef, kCRMName"- ModemDriver: Couldn't start write", status);
  1234.         } else {
  1235.             writeActive++;
  1236.             status = 1;                        // pending
  1237.         }
  1238.     } else {
  1239.         status = ioErr;
  1240.     }
  1241.     return status;
  1242. }
  1243.  
  1244. /************************************************************************************/
  1245. //
  1246. //    KillUSBIO
  1247. //
  1248. //    Kill all USB io operations in progress.
  1249. //
  1250. /************************************************************************************/
  1251.  
  1252. void KillUSBIO(void)
  1253. {
  1254.     IOParam             *pb;
  1255.     ShimSerialGlobals     *globals = gGlobals;
  1256.     
  1257.     StatusMessage(gSerialGlobals.deviceRef, kCRMName"- Modem: Killing all USB IO", 0);
  1258.  
  1259.     if (gSerialGlobals.bulkIn){
  1260.         USBAbortPipeByReference(gSerialGlobals.bulkIn);
  1261.         gSerialGlobals.bulkIn = nil;
  1262.     }
  1263.     if (gSerialGlobals.bulkOut){
  1264.         USBAbortPipeByReference(gSerialGlobals.bulkOut);
  1265.         gSerialGlobals.bulkOut = nil;
  1266.     }
  1267.     if (gSerialGlobals.interrupt){
  1268.         USBAbortPipeByReference(gSerialGlobals.interrupt);
  1269.         gSerialGlobals.interrupt = nil;
  1270.     }
  1271.     
  1272.     pb = (IOParam *)globals->pbIn;
  1273.     if (pb) {
  1274.         ShimIOComplete((union ParamBlockRec *)pb, ioErr);
  1275.         globals->pbIn = nil;
  1276.     }
  1277.     pb = (IOParam *)globals->pbOut;
  1278.     if (pb) {
  1279.         ShimIOComplete((union ParamBlockRec *)pb, ioErr);
  1280.         globals->pbOut = nil;
  1281.     }
  1282. }
  1283.  
  1284. /************************************************************************************/
  1285. //
  1286. //    InitLineCoding
  1287. //
  1288. //    Store the initial line settings.
  1289. //
  1290. /************************************************************************************/
  1291.  
  1292. void InitLineCoding(LineParms Line_Coding)
  1293. {
  1294.     serPB     *sp = &gSerialGlobals;
  1295.     
  1296.     TraceMessage(0, kCRMName"- Entering InitLineCoding");
  1297.         
  1298.     // save the settings
  1299.     sp->Line_Settings.DTERate1 = Line_Coding.DTERate1;
  1300.     sp->Line_Settings.DTERate2 = Line_Coding.DTERate2;
  1301.     sp->Line_Settings.CharFormat = Line_Coding.CharFormat;
  1302.     sp->Line_Settings.ParityType = Line_Coding.ParityType;
  1303.     sp->Line_Settings.DataBits = Line_Coding.DataBits;
  1304. }
  1305.  
  1306. /************************************************************************************/
  1307. //
  1308. //    DoDelay
  1309. //
  1310. //    Set up to do a USB delay.
  1311. //
  1312. /************************************************************************************/
  1313.  
  1314. void DoDelay(void)
  1315. {
  1316. serPB     *sp = &gSerialGlobals;
  1317.     
  1318.     TraceMessage(0, kCRMName"- Entering DoDelay");
  1319.     
  1320.     if (TimeoutDelayRequest())
  1321.         return;
  1322.             
  1323.     delayPB.usbStatus = noErr;
  1324.     delayPB.usbReference = sp->deviceRef;
  1325.     delayPB.usbRefcon = 1;
  1326.     delayPB.usbReqCount = 5;            // ~5ms (actually 5 frames at 1ms each)
  1327.     USBDelay(&delayPB);    
  1328. }
  1329.  
  1330. /************************************************************************************/
  1331. //
  1332. //    delayHandler
  1333. //
  1334. //    Completion handler for USB delay.
  1335. //
  1336. /************************************************************************************/
  1337.  
  1338. static void delayHandler(USBPB *pb)
  1339. {
  1340. serPB     *sp = &gSerialGlobals;
  1341.  
  1342.     TraceMessage(0, kCRMName"- Entering delayHandler");
  1343.  
  1344.     if (pb->usbStatus != noErr)
  1345.         StatusMessage(sp->deviceRef, kCRMName"- ModemDriver: Delay fail?", pb->usbStatus);
  1346.  
  1347.     pb->usbStatus = kAvailableStatus;
  1348. }
  1349.  
  1350. /************************************************************************************/
  1351. //
  1352. //    ClearDevice
  1353. //
  1354. //    Set up and send ClearFeature request (for stall).
  1355. //
  1356. /************************************************************************************/
  1357.  
  1358. void ClearDevice(void)
  1359. {
  1360. serPB     *sp = &gSerialGlobals;
  1361.  
  1362.     TraceMessage(0, kCRMName"- Entering ClearDevice");
  1363.     
  1364.     if (TimeoutStallRequest())
  1365.         return;
  1366.         
  1367.     stallPB.usbStatus = noErr;
  1368.     stallPB.usbReference = sp->deviceRef;
  1369.     stallPB.usbRefcon = kEndpointStall;
  1370.     stallHandler(&stallPB);
  1371. }
  1372.  
  1373. /************************************************************************************/
  1374. //
  1375. //    stallHandler
  1376. //
  1377. //    Completion handler for clear device/stall.
  1378. //
  1379. /************************************************************************************/
  1380.  
  1381. static void stallHandler(USBPB *pb)
  1382. {
  1383. serPB         *sp = &gSerialGlobals;
  1384. OSStatus    err = 0;
  1385.  
  1386.     TraceMessage(0, kCRMName"- Entering StallHandler");
  1387.     
  1388.     if (pb->usbStatus != noErr)
  1389.     {
  1390.         USBExpertFatalError(sp->deviceRef, pb->usbStatus, kCRMName"- Driver: Stall fail?", pb->usbRefcon);
  1391.         return;
  1392.     }
  1393.     
  1394.     // May have to do more here (like find out which endpoint is stalled) which is why an FSM is used
  1395.     // For the moment it's the Comm Class endpoint 0 which we'll try to clear (interupptComplete only for now)
  1396.     do{switch(pb->usbRefcon++)
  1397.     {
  1398.         case kEndpointStall:
  1399.             pb->usbStatus = noErr;
  1400.             pb->usbReference = sp->deviceRef;
  1401.             pb->pbVersion = kUSBCurrentPBVersion;    
  1402.             pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBEndpoint);
  1403.     
  1404.             pb->usb.cntl.BRequest = kUSBRqClearFeature;
  1405.             pb->usb.cntl.WValue = 0;                        // Endpoint stall
  1406.             pb->usb.cntl.WIndex = 0;
  1407.             pb->usbReqCount = 0;
  1408.             pb->usbBuffer = nil;
  1409.  
  1410.             if(immediateError(err = USBDeviceRequest(pb)))
  1411.             {
  1412.                 StatusMessage(sp->deviceRef, kCRMName"- Driver clearing device stall error", err);
  1413.             }
  1414.         break;
  1415.         
  1416.         case kStallDone:
  1417.         // stall should now be cleared
  1418.             if (pb->usbStatus != noErr)
  1419.                 USBExpertFatalError(sp->deviceRef, pb->usbStatus, kCRMName"- Driver: stall handler err for bRequest", pb->usb.cntl.BRequest);
  1420.     
  1421.             pb->usbStatus = kAvailableStatus;
  1422.         break;
  1423.         
  1424.         default:
  1425.             StatusMessage(sp->deviceRef, kCRMName"- Internal Error unused case in stall handler", (pb->usbRefcon-1));
  1426.         break;
  1427.     }
  1428.     break;    /* only execute once, unless continue used */
  1429.     }while(1);    /* so case can be reentered with a continue */
  1430. }
  1431.  
  1432. /************************************************************************************/
  1433. //
  1434. //    ResetDevice
  1435. //
  1436. //    Resets the device (uses same PB as ClearStall).
  1437. //
  1438. /************************************************************************************/
  1439.  
  1440. void ResetDevice(void)
  1441. {
  1442. serPB     *sp = &gSerialGlobals;
  1443.  
  1444.     TraceMessage(0, kCRMName"- Entering ResetDevice");
  1445.     
  1446.     if (TimeoutStallRequest())
  1447.         return;
  1448.         
  1449.     stallPB.usbStatus = noErr;
  1450.     stallPB.usbReference = sp->deviceRef;
  1451.     stallPB.usbRefcon = kResetDevice;
  1452.     ResetHandler(&stallPB);
  1453. }
  1454.  
  1455. /************************************************************************************/
  1456. //
  1457. //    ResetHandler
  1458. //
  1459. //    Completion handler for Reset device.
  1460. //
  1461. /************************************************************************************/
  1462.  
  1463. static void ResetHandler(USBPB *pb)
  1464. {
  1465. serPB         *sp = &gSerialGlobals;
  1466. OSStatus    err = 0;
  1467.  
  1468.     TraceMessage(0, kCRMName"- Entering ResetHandler");
  1469.     
  1470.     if (pb->usbStatus != noErr)
  1471.     {
  1472.         USBExpertFatalError(sp->deviceRef, pb->usbStatus, kCRMName"- Driver: Reset fail?", pb->usbRefcon);
  1473.         return;
  1474.     }
  1475.     
  1476.     // May have to do a couple of things here 
  1477.     do{switch(pb->usbRefcon++)
  1478.     {
  1479.         case kResetDevice:
  1480.             pb->usbStatus = noErr;
  1481.             pb->usbReference = sp->deviceRef;
  1482.             pb->pbVersion = kUSBCurrentPBVersion;    
  1483.             pb->usb.cntl.WValue = 0;
  1484.             pb->usb.cntl.WIndex = 0;
  1485.             pb->usbReqCount = 0;
  1486.             pb->usbBuffer = nil;
  1487.             pb->usbFlags = 0;
  1488.  
  1489.             if(immediateError(err = USBResetDevice(pb)))
  1490.             {
  1491.                 StatusMessage(sp->deviceRef, kCRMName"- Driver reset device error", err);
  1492.             }
  1493.         break;
  1494.         
  1495.         case kResetDone:
  1496.             if (pb->usbStatus != noErr)
  1497.                 USBExpertFatalError(sp->deviceRef, pb->usbStatus, kCRMName"- Driver: reset handler err ", pb->usbRefcon);
  1498.     
  1499.             pb->usbStatus = kAvailableStatus;
  1500.         break;
  1501.         
  1502.         default:
  1503.             StatusMessage(sp->deviceRef, kCRMName"- Internal Error unused case in reset handler", (pb->usbRefcon-1));
  1504.         break;
  1505.     }
  1506.     break;    /* only execute once, unless continue used */
  1507.     }while(1);    /* so case can be reentered with a continue */
  1508. }
  1509.  
  1510. /************************************************************************************/
  1511. //
  1512. //    Asciify
  1513. //
  1514. //    Convert to Ascii character
  1515. //
  1516. /************************************************************************************/
  1517.  
  1518. UInt8 Asciify(UInt8 i)
  1519. {
  1520.  
  1521.     i &= 0xF;
  1522.     if ( i < 10 )
  1523.          return( '0' + i );
  1524.     else return( 55  + i );
  1525.     
  1526. }
  1527.  
  1528. #if ((DebugOn > 0) && (LogOn > 0))
  1529.  
  1530. #define dumplen        16        // Set this to the number of bytes to dump and the rest should work out correct
  1531.  
  1532. #define buflen        ((dumplen*2)+dumplen)+3
  1533. #define Asciistart    (dumplen*2)+3
  1534.  
  1535. /************************************************************************************/
  1536. //
  1537. //    USBLogData
  1538. //
  1539. //    Dumps the requested amount of data to the USB Expert log.
  1540. //
  1541. /************************************************************************************/
  1542.  
  1543. void USBLogData(UInt8 Dir, UInt32 Count, UInt8 *buf)
  1544. {
  1545.     UInt8        wlen, i, Aspnt, Hxpnt;
  1546.     UInt8        wchr;
  1547.     UInt8        LocBuf[buflen];
  1548.  
  1549.     for ( i=1; i<=buflen; i++)
  1550.     {
  1551.         LocBuf[i] = 0x20;
  1552.     }
  1553.     
  1554.     if (Dir == kUSBIn)
  1555.     {
  1556.         TraceMessage(1, kCRMName"- Read Complete");
  1557.     } else {
  1558.         if (Dir == kUSBOut)
  1559.         {
  1560.             TraceMessage(1, kCRMName"- Write");
  1561.         }
  1562.     }
  1563.  
  1564.     if (Count > dumplen)
  1565.     {
  1566.         wlen = dumplen;
  1567.     } else {
  1568.         wlen = Count;
  1569.     }
  1570.     
  1571.     if (wlen > 0)
  1572.     {
  1573.         Aspnt = Asciistart;
  1574.         Hxpnt = 1;
  1575.         for (i=1; i<=wlen; i++)
  1576.         {
  1577.             wchr = buf[i-1];
  1578.             LocBuf[Hxpnt++] = Asciify(wchr >> 4);
  1579.             LocBuf[Hxpnt++] = Asciify(wchr);
  1580.             if ((wchr < 0x20) || (wchr == 0x7F))         // Non printable characters
  1581.             {
  1582.                 LocBuf[Aspnt++] = 0x2E;                    // Replace with a period
  1583.             } else {
  1584.                 LocBuf[Aspnt++] = wchr;
  1585.             }
  1586.         }
  1587.         LocBuf[0] = (wlen + Asciistart) + 1;
  1588.         TraceMessage(1, LocBuf);
  1589.     } else {
  1590.         TraceMessage(1, kCRMName"- No data - Actual count=0");
  1591.     }
  1592. }
  1593. #endif